<template>
  <div class="box" id="box" v-click-outside="hide">
    <input type="text" @focus="show" id="textnode" />
    <!-- 当dom节点处理不了时， 通过父节点处理， 使用代理的方式 -->
    <div v-show="isShow">面板</div>
  </div>
</template>

<script>
// 指令特定可以复用 v-show， 核心就是控制dom， 给dom元素绑定事件
// vue简单 react容易
// 自定义指令核心就是操作dom
// 图片懒加载， 虚拟滚动
export default {
  directives: {
    clickOutside: {
      // 如果是函数等价于bind +update
      // 实际上我只要bind时有效就行， 就使用对象即可
      bind(el, bindings, vnode) {
        // el 是dom
        // bindings是相关的属性， 比如执行的函数名等， 修饰符和值
        // vnode是虚拟节点 vnode.context 上下文
        // console.log("bind");
        console.log(el, bindings, vnode);

        const handler = (e) => {
          // console.log(e.target);
          if (!el.contains(e.target)) {
            // 点击是外面
            let fn = vnode.context[bindings.expression];
            fn();
          }
        };
        el.handler = handler;
        // 只要点击的不是box中的内容就隐藏掉
        document.addEventListener("click", el.handler);
      },
      unbind(el) {
        document.removeEventListener("click", el.handler);
      },
    },
  },
  data() {
    return {
      isShow: false,
    };
  },
  methods: {
    show() {
      this.isShow = true;
    },
    hide() {
      this.isShow = false;
    },
  },
};
</script>

<style>
.box {
  display: inline-flex;
  flex-direction: column;
  border: 1px solid red;
}
</style>
